/*                                    _
 *   ___ _ __ ___ _ __ ___   ___   __| |
 *  / __| '__/ __| '_ ` _ \ / _ \ / _` |
 *  \__ \ |  \__ \ | | | | | (_) | (_| |
 *  |___/_|  |___/_| |_| |_|\___/ \__,_|                                  
 *
 * |_  _ | _  _  _ _   _ _  _  _|   | _ 
 * | |(/_||_)(/_| _\  | | |(_)(_||_||(/_
 *        |                             
 */
 
#define MODULE_NAME "Helpers"

#include "srs.helpers\enums.sp"
#include "srs.helpers\constants.sp"
#include "srs.helpers\macros.sp"

stock CountInGameHumans()
{
	new realPlayers = 0;
	FOR_EACH_HUMAN(i)
	{
		realPlayers++;
	}
	return realPlayers;
}

stock FindEntityByClassname2(startEnt, const String:classname[])
{
	/* If startEnt isn't valid shifting it back to the nearest valid one */
	while (startEnt > -1 && !IsValidEntity(startEnt)) startEnt--;
	return FindEntityByClassname(startEnt, classname);
}

//client is in-game and not a bot
stock bool:IsClientInGameHuman(client)
{
	return IsClientInGame(client) && !IsFakeClient(client);
}

stock bool:IsPlayerSpawnGhost(client)
{
	return (GetEntProp(client, Prop_Send, "m_isGhost", 1) == 1);
}

stock bool:IsSurvivorIncapacitated(client)
{
	return (GetEntProp(client, Prop_Send, "m_isIncapacitated", 1) == 1);
}

stock Float:GetEntityDistanceFromPoint(entity, const Float:pointPos[3])
{
	decl Float:entityPos[3];
	decl Float:dist;
	
	GetEntPropVector(entity, Prop_Send, "m_vecOrigin", entityPos);
	dist = GetVectorDistance(pointPos, entityPos);
	
	return dist;
}

// if _ is specified as client input the command will find a valid client itself
stock CheatCommand(client = 0, String:command[], String:arguments[] = "")
{
	if (!client || !IsClientInGame(client))
	{
		FOR_EACH_CLIENT(target)
		{
			client = target;
			break;
		}
		
		return; // case no valid Client found
	}
	
	new userFlags = GetUserFlagBits(client);
	SetUserFlagBits(client, ADMFLAG_ROOT);
	new flags = GetCommandFlags(command);
	SetCommandFlags(command, flags & ~FCVAR_CHEAT);
	FakeClientCommand(client, "%s %s", command, arguments);
	SetCommandFlags(command, flags);
	SetUserFlagBits(client, userFlags);
}

stock bool:GetSafeRoomPosition(Float:position[3])
{
	new saferoom = FindEntityByClassname(-1, "info_changelevel");
	
	if (saferoom < 0) return false; // case Finale Map
	
	GetEntityAbsOrigin(saferoom, position);
	position[2] -= 55.0; // to match GetClientAbsOrigin heights
	return true;
}

stock GetEntityAbsOrigin(entity, Float:origin[3])
{
	if (entity && IsValidEntity(entity))
	{
		decl Float:mins[3], Float:maxs[3];
		GetEntPropVector(entity, Prop_Send, "m_vecOrigin", origin);
		GetEntPropVector(entity, Prop_Send, "m_vecMins", mins);
		GetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxs);
		
		for (new i = 0; i < sizeof(mins); i++)
		{
			origin[i] += (mins[i] + maxs[i]) * 0.5;
		}
	}
}

stock L4D_GetEntityHealth(entity)
{
	return GetEntProp(entity, Prop_Send, "m_iHealth");
}

stock L4DTeam:L4D_GetClientTeam(client)
{
	return L4DTeam:GetClientTeam(client);
}

stock L4DClass:L4D_GetClientClass(client)
{
	if (L4D_GetClientTeam(client) == L4DTeam_Infected)
	{
		return L4DClass:GetEntProp(client, Prop_Send, "m_zombieClass");
	}
	else
	{
		return L4DClass_Unknown;
	}
}

stock bool:L4D_IsFinaleMapNow()
{
	return (FindEntityByClassname(-1, "trigger_finale") != -1);
}

#undef MODULE_NAME
